/**
 * @author attilax 1466519819@qq.com
 * @version  c0
 * Copyright 2013  reserved.
 *  ...to license terms.
 **/

package com.mijie.homi.search.api;

//

import java.io.IOException;
import java.lang.ref.SoftReference;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONArray;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.log4j.Logger;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.mijie.homi.common.domain.SearchResult;
import com.mijie.homi.common.domain.mood.Mood;
import com.mijie.homi.search.SearchResultProser;
import com.mijie.homi.search.domain.topic.TopicOptions;
import com.mijie.homi.search.service.index.MoodUserIndexService;
import com.mijie.homi.search.service.index.TopicIndexService;
import com.mijie.homi.search.service.index.dbc4Ibatis;
import com.mijie.homi.search.service.mood.MoodService;
import com.mijie.homi.search.service.topic.ClassifyService;
import com.mijie.homi.search.util.god;
import com.mijie.homi.search.util.js;
import com.mijie.homi.search.util.listUtil;
import com.mijie.homi.search.util.pathx;
import com.mijie.homi.search.util.securyInt;
import com.mijie.homi.search.util.tryX;
import com.mijie.indexall.AutoIndex_ContextListener;
import com.mijie.query.fulltxtControllor;
import com.mijie.query.sincinController;
import com.mijie.util.IOUtil;

@Component
@RequestMapping("/topic")
@SuppressWarnings( { "all" })
/**
 * @author attilax 1466519819@qq.com
 * @version  c0
 **/
public class TopicSearchApi {

	@Autowired
	private TopicIndexService service;
	@Autowired
	private MoodService moodService;
	@Autowired
	private ClassifyService classifyService;

	@Autowired
	@Qualifier("moodUserIndexService")
	MoodUserIndexService matchService;

	private Logger logger = Logger.getLogger(TopicSearchApi.class);
	static Map<String, Date> MapCacheTimeOutStroe = new HashMap<String, Date>();
	static Object ApplicationContextCache;

	@RequestMapping(value = "/reindex", method = RequestMethod.GET)
	// (public|private).*(.*) ^\w*(public|private)([^=])*\(.*\)([^;])*
	/**
	 * @author attilax 1466519819@qq.com
	 * @version  c0
	 **/
	public @ResponseBody
	void reindex() throws Exception {
		service.reIndex();
	}

	@RequestMapping(value = "/index", method = RequestMethod.GET)
	/**
	 * @author attilax 1466519819@qq.com
	 * @version  c0
	 **/
	public @ResponseBody
	void RAMIndex(int topicId) throws Exception {
		service.RAMIndex(topicId);
	}

	@RequestMapping(value = "/search", method = RequestMethod.GET)
	/**
	 * @author attilax 1466519819@qq.com
	 * @version  c0
	 **/
	public void searchByKeyword(String idxf, String keyword, int offset,
			int limit, HttpServletResponse response) throws Exception {
		SearchResult result = service.searchByKeyword(idxf, keyword, offset,
				limit);
		IOUtil.write(response, result.toJSON());
	}

	@RequestMapping(value = "/search/top", method = RequestMethod.GET)
	/**
	 * @author attilax 1466519819@qq.com
	 * @version  c0
	 **/
	public void listTopicOfTop(String idxf, int mood, int offset, int limit,
			HttpServletResponse response) throws Exception {
		SearchResult result = service
				.listTopicOfTop(idxf, mood, offset, limit);
		IOUtil.write(response, result.toJSON());
	}

	@RequestMapping(value = "/search/mood_match", method = RequestMethod.GET)
	/**
	 * @author attilax 1466519819@qq.com
	 * @version  c0
	 **/
	public void listTopicOfMoodMatch(String idxf, int mood, int offset,
			int limit, HttpServletResponse response) throws Exception {
		SearchResult result = service.listTopicOfMoodMatch(idxf, mood, offset,
				limit);
		IOUtil.write(response, result.toJSON());
	}

	@RequestMapping(value = "/search/new", method = RequestMethod.GET)
	/**
	 * @author attilax 1466519819@qq.com
	 * @version  c0
	 **/
	public void listTopicOfNew(String idxf, int mood, int offset, int limit,
			HttpServletResponse response, HttpServletRequest request)
			throws Exception {

		String url = "url is :";
		try {
			url = url + pathx.getRequestURLx(request);
		} catch (Exception e) {
			logger.warn(god.getTrace(e));
		}
		logger.info("-----" + url);

		SearchResult result = service
				.listTopicOfNew(idxf, mood, offset, limit);
		IOUtil.write(response, result.toJSON());
	}

	@RequestMapping(value = "/search/active", method = RequestMethod.GET)
	/**
	 * @author attilax 1466519819@qq.com
	 * @version  c0
	 **/
	public void listTopicOfActive(String idxf, int mood, int offset,
			int limit, HttpServletResponse response) throws Exception {
		SearchResult result = service.listTopicOfActive(idxf, mood, offset,
				limit);
		IOUtil.write(response, result.toJSON());
	}

	@RequestMapping(value = "/search/hot", method = RequestMethod.GET)
	/**
	 * @author attilax 1466519819@qq.com
	 * @version  c0
	 **/
	public void listTopicOfHot(String idxf, int mood, int offset, int limit,
			HttpServletResponse response) throws Exception {
		SearchResult result = service
				.listTopicOfHot(idxf, mood, offset, limit);
		IOUtil.write(response, result.toJSON());
	}

	static Map<String, SoftReference<Object>> MapCache = new HashMap<String, SoftReference<Object>>();;

	/**
	 * cache..
	 * @param key
	 * @param method4GetObj
	 * @return
	 */
	public Object testSoftReference(String key, IdefaultMethod method4GetObj) {
		Object obj = null;

		SoftReference<Object> reference = MapCache.get(key);
		if (reference != null) {
			obj = reference.get();
			if (obj != null) {
				Boolean isOutTime = (Boolean) new IdefaultMethod() {

					@Override
					public Object $(Object param) {
						try {
							Date d = MapCacheTimeOutStroe.get(param);
							Date now = new Date();
							Long pasttime = now.getTime() - d.getTime();
							if (pasttime > 1000 * 300)
								return true;
							else
								return false;
						} catch (Exception e) {
							logger.error(god.getTrace(e));
							return true;
						}
					}

				}.$(key);
				if (!isOutTime)
					return obj;
				// /some code
			}
		}
		obj = method4GetObj.$(key);
		reference = new SoftReference<Object>(obj);
		MapCache.put(key, reference);
		MapCacheTimeOutStroe.put(key, new Date());

		return obj;

		//
		// if (isOutTime) {
		// // Object obj2 = method4GetObj.$(key);
		// // SoftReference<Object> reference_o1f = new SoftReference<Object>(
		// // obj2);
		// // MapCache.put(key, reference_o1f);
		// // MapCacheTimeOutStroe.put(key, new Date());
		// } else
		// return obj;
	}

	// @js("http://localhost:10000/topic/search/match.shtml?idxf=null&userId=670970&offset=0&limit=10")
	@js("pipei prblm")
	@RequestMapping(value = "/search/match", method = RequestMethod.GET)
	/**
	 * 【匹配开始时】
	 1、仍然使用我们那套匹配算法。

	 2、读取用户心事时间轴最新一条心情或问题进行匹配，无论最新一条心情是什么属性，正面还是负面，一律不管，都当成是负面的处理。

	 返回结果
	 {
	 “idxf:”12321”,
	 ”id”:1,
	 “anonymous”:0,
	 ”title”:”good”,
	 “authorNickName”:”dss”,
	 “authorAvatar”:”a.jpg”,
	 “numOfparticipate”:12,
	 “numOfOpinion”:12,
	 “numOfConfused”:2,
	 “authorGender”:1,
	 “timelineId”:234,
	 “optionIdOfMineChoice”:234,
	 “options”:[
	 {“id”:3,”options”:”反对”,”topicId”:1,”numOfChoices”:12},
	 {“id”:2,”options”:”中立”,”topicId”:1,”numOfChoices”:12},
	 {“id”:1,”options”:”支持”,”topicId”:1,”numOfChoices”:12}
	 ]
	 }
	 ]
	 }
	 * @author attilax 1466519819@qq.com
	 * @version  c0
	 **/
	public void listTopicOfMatch(final String idxf, final int userId,
			final int offset, final int limit,
			final HttpServletResponse response,
			@js("use 4 get url info") HttpServletRequest request)
			throws Exception {
		String rsturnJson = "";
		try {
			// login url
			String url = "url is :";
			try {
				url = url + pathx.getRequestURLx(request);
			} catch (Exception e) {
				logger.warn(god.getTrace(e));
			}
			logger.info("-----" + url);
			// o1f
			Object resultCache = testSoftReference(url, new IdefaultMethod() {

				@Override
				public Object $(Object key) {

					String rsturnJson2 = (String) new tryX() {

						@Override
						public Object item(Object t) throws Exception {
							String rsturnJson = process(idxf, userId, offset,
									limit, response);
							return rsturnJson;
						}
					}.$(getDefaultJson());

					return rsturnJson2;
				}
			});

			// rsturnJson = process(idxf, userId, offset, limit, response);
			rsturnJson = (String) resultCache;
			logger.info("----out put finally start");
			IOUtil.write(response, rsturnJson);
			return;
		} catch (Exception e) {
			logger.error(god.getTrace(e));

		}
		SearchResult empty = new SearchResult();
		empty.setResult(new JSONArray());
		IOUtil.write(response, empty.toJSON());

	}

	private String process(String idxf, final int userId, int offset,
			int limit, HttpServletResponse response) throws SQLException,
			IOException {
		String rsturnJson;
		logger.info("--- getRecentlyMoodNprblm start ");
		Mood mood1 = moodService.getRecentlyMoodNprblm(userId);
		// int ttt=Integer.parseInt( mood1.getContent());
		if (mood1 == null) {
			rsturnJson = getDefaultJson();

			return rsturnJson;
		}

		// cb23
		List<String> moodIds_li = new ArrayList<String>();
		List<String> prblmIds_li = new ArrayList<String>();
		// List<Object> prblms_li = new ArrayList<Object>();
		// List<Object> moods_li = new ArrayList<Object>();
		Map<String, Map> moods_mp = new HashMap<String, Map>();
		Map<String, Map> prblms_mp = new HashMap<String, Map>();
		Map<String, Map> msgs_mp = new HashMap<String, Map>();
		List<Object> block_sincin = new ArrayList<Object>();

		/**
		 * all mood problm
		 */
		// Map<String, Map> moods_map = new HashMap<String, Map>();
		logger.info("--- search start ");
		String mood_cn = "伤心";
		
		//o1g
		String s=securyInt.getString(mood1.getContent()).trim();
		if(s.length()==0)
			return getDefaultJson();
		
		  s = mood_cn + "@" + securyInt.getString(mood1.getContent());
		fulltxtControllor c = new fulltxtControllor();
		c.wordlibcache = true;
		c.exceptUid = userId;
		c.onlyPrblm = true;
		c.search(s);
		List<Map> r = c.searchResult_li;
		int n = 0;
		// JSONArray ja=new JSONArray();
		List<Map> r2 = new ArrayList<Map>();
		// List<Integer> li2=li.subList(from, from+pagesize);

		for (Map m : r) {
			n++;

			Map m4cp = new LinkedHashMap<String, Object>();

			// m4cp.put("match", m.get("pipeidu"));

			// m4cp.put("match",securyInt.getInt(m.get("pipeidu"), 90));

			// m4cp.put("match", new Float((Float) m.get("pipeidu")).intValue());
			// m4cp.put("gender", 1);
			// m4cp.put("mood", 1);
			// m4cp.put("userId", 277932);
			// // m4cp
			// .put("avatar",
			// "nullavatar/small/812a2b13-aa84-40f6-a1ae-c28a5d29448d.jpg");
			// m4cp.put("distance", 0);
			// m4cp.put("nickName", "");
			// m4cp.put("moodContent", m.get("content"));
			// m4cp.put("moodVisibility", 1);
			// m4cp.put("lastLoginAt", 1386875326000l);
			// m4cp.put("moodProtected", false);
			// o1

			if (n <= 100) {
				r2.add(m4cp);
				String fromx = securyInt.getString(m.get("fromx"),
						sincinController.sincinlib);
				;
				String id = (String) m.get("id");
				if (fromx.equals(matchService.problemlib)) {

					prblmIds_li.add(id);
					// prblm_li.add(m4cp);
					msgs_mp.put("pr" + id, m4cp);
					prblms_mp.put(id, m4cp);

				} else {

					moodIds_li.add(id);
					msgs_mp.put("sc" + id, m4cp);
					moods_mp.put(id, m4cp);

				}
				// moods_map.put(id, m4cp);

				// msg_li.add(m4cp);
			} else
				break;
		}
		// 结尾for
		List del_sincin_markDelete_set = new ArrayList<String>();
		Set moodIds_except = new HashSet<String>();
		List msg_del_by_gender = new ArrayList<Object>();
		Set prblmIds_except = new HashSet<String>();
		List del_Msg_ByHeminLen = new ArrayList<Object>(); // nbt
		Set userID_deduli_set = new HashSet<String>();
		List msg_wait_del_byDuliUser = new ArrayList<Object>();
		// o12
		List msg_wait_hid_byAnonymosPrblm = new ArrayList<Object>();
		// o12
		List msg_wait_hid_byMktDelPrblm = new ArrayList<Object>();
		// cb23
		String sql = "";
		String userpic = "";
		logger.info("--- catch problem detail info start ");
		if (prblmIds_li.size() > 0) // cb24
		{
			// dbc=dbc4Ibatis;
			String prblmIds_str = listUtil.toString(prblmIds_li, ",");
			// sql =
			// "select *,  e.lastloginat from topic m,user u ,userExtInfo e where  m.author=u.id   and u.id=e.id and m.id in (@ids) order by m.id desc limit 100";

			// select *,u.id uid,e.lastloginat from mood m,user
			// u,userExtInfo e where m.userid=u.id and u.id=e.id
			// sql = sql.replaceAll("@ids", prblmIds_str);
			// logger.info(sql);
			ResultSet rs = matchService.dbc4Ibatis.getrs("getTopicsByIds",
					prblmIds_str);
			while (rs.next()) {
				String id = rs.getString("id");

				final Map mood_m = msgs_mp.get("pr" + id);
				// o12
				String markDelete_s = rs.getString("markDelete");
				if (markDelete_s.equals("1")) {
					msg_wait_hid_byMktDelPrblm.add(mood_m);
				}

				// nbt
				String txt_fromPrblmLib = securyInt.getString(rs
						.getString("title"));

				matchService.add_set_del_by_heminLen(del_Msg_ByHeminLen, rs,
						mood_m);
				//
				final int topicID = securyInt.getInt(rs.getObject("id"), 1);
				mood_m.put("id", topicID);
				mood_m.put("idxf", "10");
				mood_m.put("numOfParticipate", rs.getInt("numOfParticipate"));
				// String txt_fromPrblmLib = rs.getString("title");
				mood_m.put("title", txt_fromPrblmLib);
				mood_m.put("author", rs.getLong("author"));
				mood_m.put("authorGender", 1);
				mood_m.put("authorNickName", rs.getString("nickName"));
				// mood_m.put("mood", 7);
				mood_m.put("authorAvatar", userpic + rs.getString("avatar"));
				mood_m.put("timelineId", rs.getInt("timelineId"));

				// mood_m.put("lastLoginAt", rs.getTimestamp("lastloginat")
				// .getTime());
				// o19
				// Timestamp ts_publishTime = (Timestamp) rs
				// .getTimestamp("createAt");
				// mood_m.put("createAt", ts_publishTime.getTime());

				// mood_m.put("gender", rs.getInt("gender"));
				// tbn hide hide msg
				int visibility = securyInt.getInt(rs.getString("visible"), 1);
				if (visibility > 1) {
					String id_md = god.getUUid4msg(mood_m.get("userId")
							.toString(), mood_m.get("moodContent").toString(),
							mood_m.get("lastLoginAt").toString());
					moodIds_except.add(id_md);

				}
				// /
				// O11 obder by nenv
				// int nenv = securyInt.getInt(mood_m.get("gender"), 0);
				// if (gender != 0)
				// if (nenv != gender)
				// msg_del_by_gender.add(mood_m);

				// o12

				int anonymous = securyInt.getInt(rs.getString("anonymous"), 0);
				mood_m.put("anonymous", anonymous);
				// if (anonymous == 1)
				// msg_wait_hid_byAnonymosPrblm.add(mood_m);

				mood_m.put("anonymous", anonymous);

				mood_m.put("numOfOpinion", rs.getInt("numOfOpinion"));
				mood_m.put("numOfConfused", rs.getInt("numOfConfused"));

				// int mychoiceID= this.sqlSession
				// .selectOne("getOptionIdByUid", userId);

				// o1f
				Integer mychoiceID = (Integer) new tryX() {

					@Override
					public Object item(Object t) throws Exception {
						Map<String, Object> parameter = new HashMap<String, Object>();
						parameter.put("tid", topicID);
						parameter.put("uid", userId);
						int mychoiceID = securyInt.getInt(sqlSession
								.selectOne("getOptionIdByUid", parameter), 0);

						return mychoiceID;
					}
				}.$(0);
				mood_m.put("optionIdOfMineChoice", mychoiceID);

				// o1f

				List<TopicOptions> listOptions_li = this.sqlSession
						.selectList("listOptions", topicID);
				// List<Map>
				// Map bookMap = PropertyUtils.describe(listOptions_li);
				mood_m.put("options", listOptions_li);

				// mood_m.put("ttt",234);

			}
		}

		// private int offset;
		// private int limit;
		// private int userId;
		// private Map<String, Map> msgs_mp;
		// private List<String> moodIds_li;
		// private List<Map> msg_wait_hid_byMktDelPrblm;
		//
		// private List<Map> del_Msg_ByHeminLen;
		//
		// private Map<String, Map> moods_mp;
		logger.info("--- SearchResultProserThis start ");
		SearchResultProser SearchResultProserThis = getSearchResultProser_o1g();

		SearchResultProserThis.setParam(offset, limit, userId, msgs_mp,
				prblmIds_li, prblmIds_li, msg_wait_hid_byMktDelPrblm,
				del_Msg_ByHeminLen, moods_mp).setIdxf(idxf);

		List li = SearchResultProserThis.process(r2);
		SearchResult resultx = getSearchResult(li);
		logger.info("--- output  start ");
		// SearchResult resultx = matchService.match(idxf, offset, limit, userId, 0);
		String json_o1f = resultx.toJSON();
		IOUtil.write(response, json_o1f);

		logger.debug("-------------search api rewerite :" + json_o1f);
		rsturnJson = json_o1f;

		// if (conditionCompilerPass())
		// return;
		return rsturnJson;
	}

	public String getDefaultJson() {
		String rsturnJson;
		SearchResult empty = new SearchResult();
		empty.setResult(new JSONArray());
		rsturnJson = empty.toJSON();
		return rsturnJson;
	}

	/**
	 * SearchResult result = null;
			Mood mood = moodService.getRecentlyMood(userId);
			if (mood != null && !mood.getContent().isEmpty()) {
				StringTokenizer tokenizer = new StringTokenizer(mood
						.getContent(), ",，.。?？!！");
				List<Set<String>> keywordGroup = new ArrayList<Set<String>>();
				String token = null;
				while (tokenizer.hasMoreTokens()) {
					token = tokenizer.nextToken();
					Set<String> keywords = classifyService.getKeywords(token);
					if (!keywords.isEmpty()) {
						keywordGroup.add(keywords);
					}
				}

				if (!keywordGroup.isEmpty()) {
					String type = classifyService.classify(mood.getContent());
					result = service.smartMatch(idxf, keywordGroup, type,
							offset, limit);
					rsturnJson= result.toJSON();
					 
				}

			}
	 * @return
	 */
	private SearchResultProser getSearchResultProser_o1g() {
		SearchResultProser SearchResultProserThis = createSearchResultProser();
		if (SearchResultProserThis == null) {
			try {
				logger
						.warn(" look up method not teke effke: will from web Appcontext getbean SearchResultProser: ");
				SearchResultProserThis = (SearchResultProser) AutoIndex_ContextListener.ctx
						.getBean("searchResultProser");
				logger
						.info(" getbean sucess  frm  AutoIndex_ContextListener.ctx :"
								+ SearchResultProserThis);
			} catch (Exception e) {
				logger.warn(" getbean from webCtx error: info is follow:");
				logger.warn(god.getTrace(e));
				logger
						.warn("cause getbean from webCtx error ,now getBeanSearchResultProserFromFilesys create :"
								+ SearchResultProserThis);

			}
		}
		// o1g
		if (SearchResultProserThis == null) {
			try {
				SearchResultProserThis = getBeanSearchResultProserFromFilesys();
				// AppCache=SearchResultProserThis;
				logger
						.info(" getbean sucess  frm  getBeanSearchResultProserFromFilesys :"
								+ SearchResultProserThis);
			} catch (Exception e) {
				logger
						.warn("   getBeanSearchResultProserFromFilesys error: info is follow:");
				logger.warn(god.getTrace(e));
				logger
						.warn("cause getbean from getBeanSearchResultProserFromFilesys error ,now NEw create :"
								+ SearchResultProserThis);
			}

		}
		if (SearchResultProserThis == null) {
			SearchResultProserThis = new SearchResultProser();
		}
		return SearchResultProserThis;
	}

	private SearchResultProser getBeanSearchResultProserFromFilesys() {
		ApplicationContext ac = null;
		if (ApplicationContextCache == null) {
			ac = UserSearchApi.getApplicationContext("");
			ApplicationContextCache = ac;
		} else
			ac = (ApplicationContext) ApplicationContextCache;
		SearchResultProser c = (SearchResultProser) ac
				.getBean("searchResultProser");
		return c;
	}

	@Autowired
	public SqlSessionTemplate sqlSession;

	// public SearchResultProser SearchResultProserThis;
	// @js("o1d")
	// @Resource(name="searchResultProser")
	// private SearchResultProser setSearchResultProser(SearchResultProser idx) {
	// SearchResultProserThis=idx;
	// return SearchResultProserThis;
	// }

	public SearchResultProser createSearchResultProserTest() {

		return createSearchResultProser();

	};

	// @Async
	public SearchResultProser createSearchResultProser() {

		return null;
	};

	private SearchResult getSearchResult(List li) {
		try {
			JSONArray json = JSONArray.fromObject(li);
			SearchResult result = new SearchResult();
			result.setResult(json);
			return result;
		} catch (Exception e) {
			logger.warn(god.getTrace(e));
			SearchResult empty = new SearchResult();
			empty.setResult(new JSONArray());
			return empty;
		}
	}

	// @Autowired
	// @Qualifier("searchResultProser")
	// // @Resourcex
	// public SearchResultProser SearchResultProserThis;
	private boolean conditionCompilerPass() {

		return true;
	}
}